﻿using System;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Data;

namespace Komunikacija
{
    public class Datoteka
    {
        public static string imeLogDatoteke { get; set; }
        public static string imeSpremnika { get; set; }

        public static void napravi(string imeDatoteke)
        {
            imeSpremnika = imeDatoteke + "-telemetrija.txt";
            imeLogDatoteke = imeDatoteke + "-log.log";
        }
    }
    public class Start
    {
        public static bool Work;
        static void Main(string[] args)
        {
            TcpListener server = new TcpListener(5001);
            TcpClient klijenttcp = default(TcpClient);
            string imePlovidbe;
            server.Start();
            Console.WriteLine("Unesi ime plovidbe:");
            imePlovidbe = Console.ReadLine();
            Datoteka.napravi(imePlovidbe);
            Console.WriteLine("Server pokrenut");
            Work = true;
            while (Work)
            {
                if (server.Pending())
                {
                    klijenttcp = server.AcceptTcpClient();
                    Klijent klijent = new Klijent();
                    klijent.pokreni(klijenttcp);
                }
                else
                {
                    Thread.Sleep(10);
                }

            }
            Log.ispisiUDatoteku();
            klijenttcp.Close();
            server.Stop();
            Console.ReadKey();
        }
    }
    public class Log
    {

        public static List<string> logList = new List<string>();

        public static void upisi(string linija)
        {
            logList.Add(DateTime.Now.ToShortDateString() + DateTime.Now.ToShortTimeString() + ":" + DateTime.Now.Second + DateTime.Now.Millisecond + ":   " + linija);
        }
        public static void ispisiUDatoteku()
        {
            try
            {
                StreamWriter log = new StreamWriter(Datoteka.imeLogDatoteke, false);
                foreach (var item in Log.logList)
                {
                    log.WriteLine(item);
                }
                log.Close();
            }
            catch
            {
                Console.WriteLine("Nije uspio upis u datoteku");
            }
        }
        public static string getFilePath()
        {
            if (File.Exists(Datoteka.imeLogDatoteke))
            {
                return Path.GetFullPath(Datoteka.imeLogDatoteke);
            }
            else
            {
                return "greska";
            }
        }


    }

    public class Klijent
    {
        public TcpClient klijenttcp { get; private set; }
        public static Object semafor = new Object();

        public void pokreni(TcpClient noviKlijent)
        {

            klijenttcp = noviKlijent;
            Thread dretva = new Thread(komunikacija);
            dretva.Start();
        }
        private void komunikacija()
        {
            #region Inicijalizacija varijabli
            string podaci;
            bool slati = true;
            string odgovor = null;
            string varijabla = "";
            byte[] Primanje = new byte[10025];
            Byte[] Slanje = null;
            string[] split = null;
            string var, vrij;
            #endregion
            while (true)
            {
                NetworkStream networkStream = klijenttcp.GetStream();
                try
                {
                    networkStream.Read(Primanje, 0, 10025);
                }
                catch
                {
                    Console.WriteLine("Greška sa komunikacijom");
                    Log.upisi("Greška sa komunikacijom");
                    Log.ispisiUDatoteku();
                    break;
                }
                podaci = System.Text.Encoding.ASCII.GetString(Primanje);
                podaci = podaci.Substring(0, podaci.IndexOf("$"));
                if (!podaci.EndsWith(";"))
                {
                    odgovor = "Ne postoji naredba, ne završava sa ';'$";
                    Console.WriteLine("Naredba ne završava sa ';'");
                    Slanje = System.Text.Encoding.ASCII.GetBytes(odgovor);
                    try
                    {
                        networkStream.Write(Slanje, 0, Slanje.Length);
                        networkStream.Flush();
                    }
                    catch
                    {
                        Console.WriteLine("Nije uspjelo slanje, klijent ugašen");
                        Log.upisi("Nije uspjelo slanje, klijent ugašen");
                        Log.ispisiUDatoteku();
                        break;
                    }
                    continue;
                }
                podaci = podaci.Substring(0, podaci.LastIndexOf(';'));
                Naredba pars = new Naredba(podaci);


                Console.WriteLine('\n' + DateTime.Now.ToShortTimeString() + ":" + DateTime.Now.Second + ": " + podaci);
                try
                {
                    if (pars.Modul == "Administrator" && pars.Smjer == "UGASISERVER")
                    {
                        Start.Work = false;
                        Console.WriteLine("varijabla postavljena");
                        break;
                    }
                }
                catch
                {
                    Console.WriteLine("Nije uspjelo zaustavljanje poslužitelja");
                    Log.upisi("Nije uspjelo zaustavljanje poslužitelja");
                    Log.ispisiUDatoteku();
                }

                lock (semafor)
                {
                    Log.upisi(podaci);

                    #region Kraj rada

                    if ((pars.Smjer == "LOGOUT") || (pars.Smjer == "Logout") || (pars.Smjer == "logout"))
                    {
                        try
                        {
                            Log.ispisiUDatoteku();
                            odgovor = "Kraj$";
                            Slanje = System.Text.Encoding.ASCII.GetBytes(odgovor);
                            networkStream.Write(Slanje, 0, Slanje.Length);
                            break;
                        }
                        catch
                        {
                            Log.ispisiUDatoteku();
                            Console.WriteLine("Nije uspjelo odspajanje");
                            odgovor = "Kraj$";
                            Slanje = System.Text.Encoding.ASCII.GetBytes(odgovor);
                            try
                            {
                                networkStream.Write(Slanje, 0, Slanje.Length);

                            }
                            catch
                            {
                                Console.WriteLine("Nije uspjelo slanje, klijent je ugašen");
                                Log.upisi("Nije uspjelo slanje, klijent je ugašen");
                                Log.ispisiUDatoteku();
                                break;
                            }
                            break;
                        }
                    }


                    #endregion

                    else if (pars.Smjer.ToUpper().Equals("ALL"))
                    {
                        odgovor = Podaci.vratiSve() + "$";
                        Console.WriteLine("Poslane sve varijable");
                        slati = true;
                    }



                    #region Get

                    else if (pars.Smjer.ToUpper().Equals("GET"))
                    {
                        varijabla = "";

                        split = pars.Varijable.Split(';');
                        foreach (var item in split)
                        {
                            if (item.Length > 1)
                            {
                                varijabla += Podaci.nadji(item) + ";";
                            }
                            odgovor = "VAL:" + varijabla + "$";
                            slati = true;
                        }
                    }

                    else if (pars.Smjer.ToUpper().Equals("GETLOG"))
                    {
                        slati = false;
                        odgovor = Log.getFilePath() + "$";
                        Slanje = System.Text.Encoding.ASCII.GetBytes(odgovor);
                        try
                        {
                            networkStream.Write(Slanje, 0, Slanje.Length);
                            networkStream.Flush();
                            networkStream.Read(Primanje, 0, 10025);
                        }
                        catch
                        {
                            Console.WriteLine("Aplikacija na kopnu ugašena, nije uspjelo slanje");
                            Log.upisi("Aplikacija na kopnu ugašena, nije uspjelo slanje");
                            Log.ispisiUDatoteku();
                            break;
                        }
                        continue;
                    }

                    #endregion

                    #region Set
                    else if ((pars.Smjer == "SET") || (pars.Smjer == "set") || (pars.Smjer == "Set"))
                    {
                        split = pars.Varijable.Split(';');
                        foreach (var item in split)
                        {
                            if (item.Length > 1)
                            {
                                if (item.IndexOf(':') != -1)
                                {
                                    var = item.Substring(0, item.IndexOf(':'));
                                    vrij = item.Substring(item.IndexOf(':') + 1);
                                    Podaci.dodaj(var, vrij);
                                    odgovor = "VAL;SET;OK$";
                                    slati = true;
                                }
                                else
                                {
                                    odgovor = "Ne postoji naredba$";
                                    break;
                                }
                            }
                        }
                    }
                    #endregion

                    #region Kriva naredba
                    else
                    {
                        odgovor = "Ne postoji naredba$";
                    }
                    #endregion
                    if (slati == true)
                    {
                        Console.WriteLine(odgovor);
                        Slanje = System.Text.Encoding.ASCII.GetBytes(odgovor);
                        try
                        {
                            networkStream.Write(Slanje, 0, Slanje.Length);
                            networkStream.Flush();
                        }
                        catch
                        {
                            Console.WriteLine("Klijent ugašen, nije uspjelo slanje");
                            Log.upisi("Klijent ugašen, nije uspjelo slanje");
                            Log.ispisiUDatoteku();
                            break;
                        }
                        if (!pars.Smjer.ToUpper().Equals("GETLOG"))
                        {
                            Log.upisi(odgovor.Substring(0, odgovor.Length - 1));
                        }
                    }

                }
            }
        }
    }

    public class Podaci
    {

        static Dictionary<string, string> dic = new Dictionary<string, string>();


        public static void upisi(string var, string val)
        {
            dic[var] = val;
            //upisiUDatoteku(var, val);
        }

        private static void upisiUDatoteku(string var, string val)
        {
            StreamWriter ispis = new StreamWriter(Datoteka.imeSpremnika, true);
            TextWriter ispis1 = TextWriter.Synchronized(ispis);
            if (!File.Exists(Datoteka.imeSpremnika))
            {
                File.Create(Datoteka.imeSpremnika);
            }
            ispis1.WriteLine(DateTime.Now.ToShortDateString() + DateTime.Now.ToShortTimeString() + ":" + DateTime.Now.Second + ":   " + var + " " + val); ispis1.Close();
            ispis.Close();
        }
        public static string vratiSve()
        {
            string odgovor;
            odgovor = "";

            foreach (var item in dic)
            {
                odgovor += item.Key + ":" + item.Value + ";";
            }

            return odgovor;
        }

        public static string nadji(string var)
        {
            Console.WriteLine("Zatražena varijabla: {0}", var);
            if (dic.ContainsKey(var))
            {
                Console.WriteLine("Vrijednost: {0}", dic[var]);
                return dic[var];
            }
            else
            {
                Console.WriteLine("Varijabla nije pronađena");
                return "greska";
            }
        }
        public static void dodaj(string var, string vrij)
        {
            dic[var] = vrij;
            upisi(var, vrij);
            Console.WriteLine("Upisana varijabla: {0} = {1}", var, vrij);
        }
    }

    public class Naredba
    {
        public string Modul { get; set; }
        public string Smjer { get; set; } //Može biti GET ili SET
        public string Varijable { get; set; } // Popis svih varijabli

        public Naredba(string podaci)
        {
            string[] split = null;
            if (podaci.Contains(";"))
            {
                split = podaci.Split(';');
                Modul = split[0];
                Smjer = split[1];
                foreach (string item in split)
                {
                    if ((item != Modul) && (item != Smjer))
                    {
                        Varijable += item + ";";
                    }
                }
            }
            else
            {
                Smjer = "Ne postoji naredba$";
                Console.WriteLine("Primljena naredba ne sadrži ;");
            }
        }

    }

}